﻿using System;
using System.Buffers.Binary;
using System.Runtime.CompilerServices;

namespace Letter.IO.Binary;

sealed class BinaryOrderOperationLE : IBinaryOrderOperation
{
    public readonly static BinaryOrderOperationLE Instance = new BinaryOrderOperationLE();
    
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public char ReadChar(in ReadOnlySpan<byte> span) => (char) ReadInt16(span);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public short ReadInt16(in ReadOnlySpan<byte> span) => BinaryPrimitives.ReadInt16LittleEndian(span);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public ushort ReadUInt16(in ReadOnlySpan<byte> span) => BinaryPrimitives.ReadUInt16LittleEndian(span);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int ReadInt32(in ReadOnlySpan<byte> span) => BinaryPrimitives.ReadInt32LittleEndian(span);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public uint ReadUInt32(in ReadOnlySpan<byte> span) => BinaryPrimitives.ReadUInt32LittleEndian(span);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public long ReadInt64(in ReadOnlySpan<byte> span) => BinaryPrimitives.ReadInt64LittleEndian(span);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public ulong ReadUInt64(in ReadOnlySpan<byte> span) => BinaryPrimitives.ReadUInt64LittleEndian(span);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public float ReadFloat32(in ReadOnlySpan<byte> span) => BytesBufferUtil.Int32BitsToSingle(this.ReadInt32(span));
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public double ReadFloat64(in ReadOnlySpan<byte> span) => BitConverter.Int64BitsToDouble(this.ReadInt64(span));
    
    
    
    
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void WriteChar(in Span<byte> destination, char value) => this.WriteInt16(destination, (short) value);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void WriteInt16(in Span<byte> destination, short value) => BinaryPrimitives.WriteInt16LittleEndian(destination, value);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void WriteUInt16(in Span<byte> destination, ushort value) => BinaryPrimitives.WriteUInt16LittleEndian(destination, value);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void WriteInt32(in Span<byte> destination, int value) => BinaryPrimitives.WriteInt32LittleEndian(destination, value);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void WriteUInt32(in Span<byte> destination, uint value) => BinaryPrimitives.WriteUInt32LittleEndian(destination, value);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void WriteInt64(in Span<byte> destination, long value) => BinaryPrimitives.WriteInt64LittleEndian(destination, value);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void WriteUInt64(in Span<byte> destination, ulong value) => BinaryPrimitives.WriteUInt64LittleEndian(destination, value);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void WriteFloat32(in Span<byte> destination, float value) => this.WriteInt32(destination, BytesBufferUtil.SingleToInt32Bits(value));
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public void WriteFloat64(in Span<byte> destination, double value) => this.WriteInt64(destination, BitConverter.DoubleToInt64Bits(value));
}